package com.yxw.live_vod_boot.utils;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import java.io.File;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.yxw.yxnet_cd_center.common.enums.CommonErrorEnum;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;

/**
 * @author Administrator
 */
@Slf4j
@Component
public class HuaWeiObsUtil {

    
    @Value("${spring.cloud.hwy.obs.ak}")
    private String ak;
    @Value("${spring.cloud.hwy.obs.sk}")
    private String sk;
    @Value("${spring.cloud.hwy.obs.end-point}")
    private String endPoint;
    @Value("${spring.cloud.hwy.obs.bucket-name}")
    private String bucketName;
    @Value("${spring.cloud.hwy.obs.parent-dir}")
    private String parentDir;
    /**
     * 图片过期时间
     */
    @Value("${file.image.expiration-time}")
    private long fileImageExpirationTime;

    public  String getObsDownloadUrlStartPoint()
    {
        return "https://" + bucketName + "." + endPoint;
    }
    public  String getObsDownloadUrlStartPointNoEndSlash()
    {
        return "https://" + bucketName + "." + endPoint.replaceAll("/", "");
    }    
    /**
     * OBS-上传文件
     * @param objectKey 具体的文件名（含存储路径）
     * @param inputStream 输入流
     * @return PutObjectResult
     */
    public String uploadFile(String objectKey, InputStream inputStream) {
         return uploadFileByObs(objectKey, inputStream);
    }

    /**
     * @param objectKey       具体的文件名（含存储路径）
     * @param inputStream 文件流
     */
    private String uploadFileByObs(String objectKey,InputStream inputStream) {
        ObsClient obsClient = null;
        try {
            obsClient = new ObsClient(ak, sk, endPoint);
            //判断桶是否存在，不存在就创建
            boolean  bucketExist= obsClient.headBucket(bucketName);
            if(!bucketExist){
                throw new BaseException("未创建OBS桶");
            }
            PutObjectResult putObjectResult = obsClient.putObject(bucketName, objectKey, inputStream);
            System.out.println("putObjectResult.getObjectUrl():" + putObjectResult.getObjectUrl());
            System.out.println("putObjectResult.getEtag():" + putObjectResult.getEtag());
            System.out.println("putObjectResult.getBucketName():" + putObjectResult.getBucketName());
            System.out.println("putObjectResult.getObjectKey():" + putObjectResult.getObjectKey());
            System.out.println("putObjectResult.getVersionId():" + putObjectResult.getVersionId());
            System.out.println("putObjectResult.getStatusCode():" + putObjectResult.getStatusCode());
            System.out.println("putObjectResult.toString():" + putObjectResult.toString());
//            return this.downloadFile(result.getObjectKey(), fileImageExpirationTime);
            return getObsDownloadUrlStartPoint()+objectKey;
        } catch (Exception e) {
            log.error("OBS上传文件报错ObsException:{}", e.getMessage());
            throw new BaseException("上传文件失败："+e.getMessage());
        } finally {
            if (Optional.ofNullable(obsClient).isPresent()) {
                try {
                    obsClient.close();
                } catch (IOException e) {
                    log.error("OBS关闭连接报错！===============" + e.getMessage());
                }
            }
        }
    }

    /**
     * 删除单个对象
     * @return boolean
     */
    public boolean deleteFile(String objectKey) {
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        DeleteObjectResult deleteObjectResult = obsClient.deleteObject(bucketName, objectKey);
        boolean deleteMarker = deleteObjectResult.isDeleteMarker();
        try {
            obsClient.close();
        } catch (IOException e) {
            log.error("华为OBS关闭客户端失败", e);
        }
        return deleteMarker;
    }

    /**
     * OBS-下载文件（获取对象）
     * @param objectKey 具体的文件名（含存储路径）
     * @return ObsObject
     */
    public String downloadFile(String objectKey,long expirationTime) {
        ObsClient obsClient = null;
        try {
            obsClient = new ObsClient(ak, sk, endPoint);
            TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, expirationTime);
            request.setBucketName(bucketName);
            request.setObjectKey(objectKey);
            TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
            if(ObjectUtils.isEmpty(response.getSignedUrl())){
                log.error("获取临时文件失败" + response);
                throw new BaseException("获取临时文件失败");
            }
            return response.getSignedUrl();
        } catch (ObsException e) {
            log.error("OBS上传文件报错ObsException===============" + e.getMessage());
        } catch (Exception e) {
            log.error("OBS下载文件报错Exception===============" + e.getMessage());
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (IOException e) {
                    log.error("OBS关闭连接报错！===============" + e.getMessage());
                }
            }
        }
        return null;
    }
    
    public ObsClient getObsClient()
    {
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        //判断桶是否存在，不存在就创建
        boolean  bucketExist= obsClient.headBucket(bucketName);
        if(!bucketExist)
        {
            throw new BaseException("未创建OBS桶");
        }
        return obsClient;
    }
    /**
     * OBS-上传文件
     *
     * @param objectKey   具体的文件名（含存储路径）
     * @param inputStream 输入流
     * @return PutObjectResult
     */
    public  PutObjectResult uploadFileInputStream(String objectKey, InputStream inputStream) {
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        //判断桶是否存在，不存在就创建
        boolean  bucketExist= obsClient.headBucket(bucketName);
        if(!bucketExist)
        {
            throw new BaseException("未创建OBS桶");
        }      
        return uploadWithObs(obsClient, objectKey, null, inputStream);
    }    
  
    /**
     * OBS-上传文件
     *
     * @param objectKey   具体的文件名（含存储路径）
     * @param inputStream 输入流
     * @return PutObjectResult
     */
    public  PutObjectResult uploadFileInputStream(ObsClient obsClient, String objectKey, InputStream inputStream) {
        return uploadWithObs(obsClient, objectKey, null, inputStream);
    }

    /**
     * OBS-上传文件
     *
     * @param objectKey 具体的文件名（含存储路径）
     * @param file      文件
     * @return PutObjectResult
     */
    public  PutObjectResult uploadFile(ObsClient obsClient, String objectKey, File file) {
        return uploadWithObs(obsClient, objectKey, file, null);
    }

    /**
     * @param objectKey       具体的文件名（含存储路径）
     * @param file            文件
     * @param fileInputStream 文件流
     */
    private  PutObjectResult uploadWithObs(ObsClient obsClient, String objectKey, File file, InputStream fileInputStream) {
        PutObjectResult putObjectResult = null;
        try
        {
            if (Optional.ofNullable(file).isPresent()) {
                putObjectResult = obsClient.putObject(bucketName, objectKey, file);
            } 
            else {
                putObjectResult = obsClient.putObject(bucketName, objectKey, fileInputStream);
            }
            System.out.println("putObjectResult.getObjectUrl():" + putObjectResult.getObjectUrl());
            System.out.println("putObjectResult.getEtag():" + putObjectResult.getEtag());
            System.out.println("putObjectResult.getBucketName():" + putObjectResult.getBucketName());
            System.out.println("putObjectResult.getObjectKey():" + putObjectResult.getObjectKey());
            System.out.println("putObjectResult.getVersionId():" + putObjectResult.getVersionId());
            System.out.println("putObjectResult.getStatusCode():" + putObjectResult.getStatusCode());
            System.out.println("putObjectResult.toString():" + putObjectResult.toString());          
            log.info("OBS-上传文件objectKey:{},响应:{}", objectKey, putObjectResult);
        } 
        catch (ObsException e) 
        {
            log.error(e.toString());
            log.error("OBS上传文件报错ObsException:{}", e.getMessage());
            throw new BaseException(CommonErrorEnum.UPLOAD_ERROR, e.getMessage());
        } 
        catch (Exception e) 
        {
            log.error("OBS上传文件报错Exception:{}", e);
            throw new BaseException(CommonErrorEnum.UPLOAD_ERROR, e.getMessage());
        }
        finally
        { 
            try 
            {
                obsClient.close();
            }
            catch (IOException e) {
                log.error("OBS关闭连接报错！===============" + e.getMessage());
                //throw new BaseException(CommonErrorEnum.UPLOAD_ERROR, e.getMessage());
            }
        }
        if(null == putObjectResult){
            throw new BaseException(CommonErrorEnum.UPLOAD_ERROR,"OBS-上传文件失败,putObjectResult is null");
        }
        if(putObjectResult.getStatusCode() != 200){
            throw new BaseException(CommonErrorEnum.UPLOAD_ERROR,"OBS-上传文件失败,StatusCode = " + putObjectResult.getStatusCode());
        }        
        return putObjectResult;
    }

    /**
     * OBS-上传文件
     *
     * @param objectKey 具体的文件名（含存储路径）
     * @param fileInputStream 文件流
     * @return PutObjectResult
     */
    public  PutObjectResult uploadStreamNotClose(ObsClient obsClient, String objectKey, InputStream fileInputStream) {
        return uploadFileByObsNotClose(obsClient, objectKey, null,fileInputStream);
    }    
    /**
     * @param objectKey       具体的文件名（含存储路径）
     * @param file            文件
     * @param fileInputStream 文件流
     */
    private  PutObjectResult uploadFileByObsNotClose(ObsClient obsClient, String objectKey, File file, InputStream fileInputStream) {
        PutObjectResult putObjectResult = null;
        try
        {
            if (Optional.ofNullable(file).isPresent())
            {
                putObjectResult = obsClient.putObject(bucketName, objectKey, file);
            } 
            else 
            {
                putObjectResult = obsClient.putObject(bucketName, objectKey, fileInputStream);
            }
            log.info("OBS-上传文件objectKey:{},响应:{}", objectKey, putObjectResult);
            System.out.println("putObjectResult.getObjectUrl():" + putObjectResult.getObjectUrl());
            System.out.println("putObjectResult.getEtag():" + putObjectResult.getEtag());
            System.out.println("putObjectResult.getBucketName():" + putObjectResult.getBucketName());
            System.out.println("putObjectResult.getObjectKey():" + putObjectResult.getObjectKey());
            System.out.println("putObjectResult.getVersionId():" + putObjectResult.getVersionId());
            System.out.println("putObjectResult.getStatusCode():" + putObjectResult.getStatusCode());
            System.out.println("putObjectResult.toString():" + putObjectResult.toString());            
        } 
        catch (ObsException e) 
        {
            //log.error(e.toString());
            log.error("OBS上传文件报错ObsException:{}", e.getMessage());
            throw new BaseException(CommonErrorEnum.UPLOAD_ERROR, e.getMessage());
        } 
        catch (Exception e) 
        {
            log.error("OBS上传文件报错Exception:{}", e);
            throw new BaseException(CommonErrorEnum.UPLOAD_ERROR, e.getMessage());
        }
        if(null == putObjectResult)
        {
            throw new BaseException("OBS-上传文件失败,putObjectResult is null");
        }
        if(putObjectResult.getStatusCode() != 200)
        {
            throw new BaseException("OBS-上传文件失败,StatusCode = " + putObjectResult.getStatusCode());
        }
        return putObjectResult;
    } 
    /**
     * @param obsClient       obs客户端
     * @param objectKey       具体的文件名（含存储路径）     
     * @param fileInputStream 文件流
     */
    public PutObjectResult uploadStreamWithObsClient(ObsClient obsClient, String objectKey, InputStream fileInputStream) throws Exception
    {
         PutObjectResult putObjectResult = null;   
         putObjectResult = obsClient.putObject(bucketName, objectKey, fileInputStream);
         return putObjectResult;
    } 
    /**
     * @param objectKey       具体的文件名（含存储路径）
     * @param fileInputStream 文件流
     */
    public PutObjectResult uploadStream( String objectKey, InputStream fileInputStream) throws Exception
    {
        ObsClient obsClient = new ObsClient(ak, sk, endPoint);
        //判断桶是否存在，不存在就创建
        boolean  bucketExist= obsClient.headBucket(bucketName);
        if(!bucketExist)
        {
            throw new BaseException("未创建OBS桶");
        } 
        PutObjectResult putObjectResult = null;   
        putObjectResult = obsClient.putObject(bucketName, objectKey, fileInputStream);
            System.out.println("putObjectResult.getObjectUrl():" + putObjectResult.getObjectUrl());
            System.out.println("putObjectResult.getEtag():" + putObjectResult.getEtag());
            System.out.println("putObjectResult.getBucketName():" + putObjectResult.getBucketName());
            System.out.println("putObjectResult.getObjectKey():" + putObjectResult.getObjectKey());
            System.out.println("putObjectResult.getVersionId():" + putObjectResult.getVersionId());
            System.out.println("putObjectResult.getStatusCode():" + putObjectResult.getStatusCode());
            System.out.println("putObjectResult.toString():" + putObjectResult.toString());        
        obsClient.close();
        return putObjectResult;
    }      
    /**
     * 删除单个对象
     * @return boolean
     */
    public boolean deleteFileNotClose(ObsClient obsClient,String objectKey)
    {
        DeleteObjectResult deleteObjectResult = obsClient.deleteObject(bucketName, objectKey);
        boolean deleteMarker = deleteObjectResult.isDeleteMarker();
        return deleteMarker;
    }    
}
